<html>
<head>
  <title>Evernote Export</title>
  <basefont face="微软雅黑" size="2" />
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
  <meta name="exporter-version" content="YXBJ Windows/600753 (zh-CN, DDL); Windows/10.0.0 (Win64);"/>
  <style>
    body, td {
      font-family: 微软雅黑;
      font-size: 10pt;
    }
  </style>
</head>
<body>
<a name="1366"/>

<div>
<span><div>代码思路 读入一个证件照 </div><div>对变量进行初始化 宽高层数大小</div><div>建立一个MAT</div><div>把对应的像素点复制给新的Mat</div><div>建立一个TermCritria函数 （具体使用方法已经录入笔记）</div><div>使用meanshift</div><div>把他们的颜色进行判断区分成不同的簇</div><div>Cindex是找出以背景为代表的颜色和他对应的簇</div><div>labels存入元素对应的簇值</div><div>最后让其变成二值图</div><div>通过高斯模糊+腐蚀</div><div>定义一个Vec3b color的变量 这个设定成需要换成什么背景的值</div><div>循环进行判断黑白来改变元素值 黑的改成color新的背景 白的从原本的图像中提取原本的颜色</div><div style="box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, &quot;Courier New&quot;, monospace; font-size: 12px; color: rgb(51, 51, 51); border-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.15);-en-codeblock:true;"><div>#include&quot;pch.h&quot;</div><div>#include &lt;opencv2/opencv.hpp&gt;</div><div>#include &lt;opencv2/xfeatures2d.hpp&gt;</div><div>#include &lt;opencv2/face.hpp&gt;</div><div>#include &lt;iostream&gt;</div><div>#include &lt;math.h&gt;</div><div>#include &lt;string&gt;</div><div>#include &lt;fstream&gt;</div><div>using namespace cv::face;</div><div>using namespace cv;</div><div>using namespace std;</div><div>using namespace cv::xfeatures2d;</div><div>int  main() {</div><div>        Mat src = imread(&quot;A.png&quot;);</div><div>        imshow(&quot;src&quot;, src);</div><div>        //组装数据</div><div>        int width = src.cols;</div><div>        int height = src.rows;</div><div>        int samplecount = width * height;</div><div>        int dims = src.channels();//图片的层数</div><div>        //行数为src的像素点数，列数为通道数，每列数据分别为src的bgr，从上到下 从左到右顺序读数据</div><div>        Mat points(samplecount, dims, CV_32F, Scalar(10));</div><div>        int ind = 0;</div><div>        for (int row = 0; row &lt; height; row++) {</div><div>               for (int col = 0; col &lt; width; col++) {</div><div>                       ind = row * width + col;//</div><div>                       Vec3b bgr = src.at&lt;Vec3b&gt;(row, col);</div><div>                       points.at&lt;float&gt;(ind, 0) = static_cast&lt;int&gt;(bgr[0]);</div><div>                       points.at&lt;float&gt;(ind, 1) = static_cast&lt;int&gt;(bgr[1]);</div><div>                       points.at&lt;float&gt;(ind, 2) = static_cast&lt;int&gt;(bgr[2]);</div><div>               }</div><div>        }</div><div>        //运行kmeans</div><div>        int numCluster = 4;</div><div>        Mat labels;</div><div>        Mat centers;</div><div>        TermCriteria criteria = TermCriteria(TermCriteria::EPS +  TermCriteria::COUNT,10,0.1);</div><div>        kmeans(points, numCluster, labels, criteria, 3, KMEANS_PP_CENTERS, centers);</div><div>        </div><div>        //去背景+遮罩生成</div><div>        Mat mask = Mat::zeros(src.size(), CV_8UC1);</div><div>        int index = src.rows * 2 + 2;//不取边缘的左上点，往里靠2个位置</div><div>        int cindex = labels.at&lt;int&gt;(index,0);</div><div>        int height1 = src.rows;</div><div>        int width1 = src.cols;</div><div>        Mat dst;//人的轮廓周围会有一些杂点，所以需要腐蚀和高斯模糊取干扰</div><div>        src.copyTo(dst);</div><div>        for (int row = 0; row &lt; height1; row++) {</div><div>               for (int col = 0; col &lt; width1; col++) {</div><div>                       index = row * width1 + col;</div><div>                       int label = labels.at&lt;int&gt;(index, 0);</div><div>                       if (label == cindex) {</div><div>                              dst.at&lt;Vec3b&gt;(row, col)[0] = 0;</div><div>                              dst.at&lt;Vec3b&gt;(row, col)[1] = 0;</div><div>                              dst.at&lt;Vec3b&gt;(row, col)[2] = 0;</div><div>                              mask.at&lt;uchar&gt;(row, col) = 0;</div><div>                       }</div><div>                       else {</div><div>                              dst.at&lt;Vec3b&gt;(row, col) = src.at&lt;Vec3b&gt;(row, col);</div><div>                              mask.at&lt;uchar&gt;(row, col) = 255;//人脸部分设为白色，以便于下面的腐蚀与高斯模糊</div><div>                       }</div><div>               }</div><div>        }</div><div>        imshow(&quot;dst&quot;, dst);</div><div>        imshow(&quot;mask&quot;, dst);</div><div>        //腐蚀+高斯模糊</div><div>        Mat k = getStructuringElement(MORPH_RECT, Size(3, 3));</div><div>        erode(mask, mask, k);</div><div>        GaussianBlur(mask, mask, Size(3, 3), 0, 0);</div><div>        imshow(&quot;gaosimohu&quot;, mask);</div><div>        //通道混合</div><div>        RNG rng(12345);</div><div>        Vec3b color;</div><div>        color[0] = 180;//rng.uniform(0, 255);</div><div>        color[1] = 180;//rng.uniform(0, 255);</div><div>        color[2] = 238;//rng.uniform(0, 255);</div><div>        Mat result(src.size(), src.type());</div><div>        double w = 0.0;</div><div>        int b = 0, g = 0, r = 0;</div><div>        int b1 = 0, g1 = 0, r1 = 0;</div><div>        int b2 = 0, g2 = 0, r2 = 0;</div><div>        double time = getTickCount();</div><div>        for (int row = 0; row &lt; height1; row++) {</div><div>               for (int col = 0; col &lt; width; col++) {</div><div>                       int m = mask.at&lt;uchar&gt;(row, col);</div><div>                       if (m == 255) {</div><div>                              result.at&lt;Vec3b&gt;(row, col) = src.at&lt;Vec3b&gt;(row, col);//前景</div><div>                       }</div><div>                       else if (m == 0) {</div><div>                              result.at&lt;Vec3b&gt;(row, col) = color; // 背景</div><div>                       }</div><div>                       else {//因为高斯模糊的关系，所以mask元素的颜色除了黑白色还有黑白边缘经过模糊后的非黑白值</div><div>                              w = m / 255.0;</div><div>                              b1 = src.at&lt;Vec3b&gt;(row, col)[0];</div><div>                              g1 = src.at&lt;Vec3b&gt;(row, col)[1];</div><div>                              r1 = src.at&lt;Vec3b&gt;(row, col)[2];</div><div>                              b2 = color[0];</div><div>                              g2 = color[0];</div><div>                              r2 = color[0];</div><div>                              b = b1 * w + b2 * (1.0 - w);</div><div>                              g = g1 * w + g2 * (1.0 - w);</div><div>                              r = r1 * w + r2 * (1.0 - w);</div><div>                              result.at&lt;Vec3b&gt;(row, col)[0] = b;//最终边缘颜色值</div><div>                              result.at&lt;Vec3b&gt;(row, col)[1] = g;</div><div>                              result.at&lt;Vec3b&gt;(row, col)[2] = r;</div><div>                       }</div><div>               }</div><div>        }</div><div>        cout &lt;&lt; &quot;time=&quot; &lt;&lt; (getTickCount() - time) / getTickFrequency() &lt;&lt; endl;</div><div>        imshow(&quot;backgroud repalce&quot;, result);</div><div>        waitKey(0);</div><div>}</div></div><div><br/></div></span>
</div></body></html> 